/**
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package trim.gui.testing.models;

import java.awt.Component;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JComponent;
import javax.swing.JTabbedPane;
import javax.swing.table.AbstractTableModel;
import trim.Trim;
import trim.common.inputdata.FormatOrder;
import trim.common.inputdata.MaterialStock;
import trim.common.inputdata.InputData;
import trim.common.result.TrimResult;
import trim.gui.testing.export.ExportManager;
import trim.gui.testing.objects.ResultsListItem;
import trim.scripting.interfaces.IResultListManager;

/**
 *
 * @author Дмитрий
 */
public class ResultListTableModel extends AbstractTableModel implements IResultListManager
{

  //private List<ResultsListItem> resultsList=new ArrayList();
  private ResultsTableModel resultsTableModel=new ResultsTableModel();
  private List<InputData> requests=new ArrayList();
  private List<Map<String,ResultsListItem>> results=new ArrayList();

  public ResultListTableModel()
  {
  }

  public List<Map<String,ResultsListItem>> getResults()
  {
    return results;
  }

  /**
   * Сранение двух входных данных на равенство
   * @param d1
   * @param d2
   * @return
   */
  private boolean compareInputData(InputData d1,InputData d2)
  {
    if(d1.getFormatOrderList().size()!=d2.getFormatOrderList().size())
      return false;
    FormatOrder[] fc1=d1.getFormatOrderList().toArray(new FormatOrder[0]);
    FormatOrder[] fc2=d2.getFormatOrderList().toArray(new FormatOrder[0]);
    Comparator c=new Comparator<FormatOrder>()
    {

      @Override
      public int compare(FormatOrder o1,FormatOrder o2)
      {
        if(o1.getFormat().getLength()>o2.getFormat().getLength())
          return 1;
        else if(o1.getFormat().getLength()<o2.getFormat().getLength())
          return -1;
        else
          return 0;
      }
    };
    Arrays.sort(fc1,c);
    Arrays.sort(fc2,c);
    for(int i=0;i<fc1.length;i++)
      if(!fc1[i].equals(fc2[i]))
        return false;
    if(d1.getMaterialStockList().size()!=d2.getMaterialStockList().size())
      return false;
    MaterialStock[] mc1=d1.getMaterialStockList().toArray(new MaterialStock[0]);
    MaterialStock[] mc2=d2.getMaterialStockList().toArray(new MaterialStock[0]);
    c=new Comparator<MaterialStock>()
    {

      public int compare(MaterialStock o1,MaterialStock o2)
      {
        if(o1.getMaterial().getLength()>o2.getMaterial().getLength())
          return 1;
        else if(o1.getMaterial().getLength()<o2.getMaterial().getLength())
          return -1;
        else
          return 0;
      }
    };
    Arrays.sort(mc1,c);
    Arrays.sort(mc2,c);
    for(int i=0;i<mc1.length;i++)
      if(!mc1[i].equals(mc2[i]))
        return false;
    return true;
  }

  public void selectTest(int t)
  {
    List l=new ArrayList();
    Map m=results.get(t);
    for(Object o:m.values())
      l.add(o);
    resultsTableModel.setResults(l);
  }

  public ResultsTableModel getResultsTableModel()
  {
    return resultsTableModel;
  }

  @Override
  public int getRowCount()
  {
    return requests.size();
  }

  @Override
  public int getColumnCount()
  {
    return 5;
  }

  @Override
  public String getColumnName(int column)
  {
    switch(column)
    {
      case 0:
        return "#";
      case 1:
        return "Formats";
      case 2:
        return "Materials";
      case 3:
        return "Formats Area";
      case 4:
        return "Materials Area";
    }
    return "";
  }

  @Override
  public Class<?> getColumnClass(int columnIndex)
  {
    switch(columnIndex)
    {
      case 0:
        return String.class;
      case 1:
        return Integer.class;
      case 2:
        return Integer.class;
      case 3:
        return Integer.class;
      case 4:
        return Integer.class;
    }
    return Object.class;
  }

  @Override
  public Object getValueAt(int rowIndex,int columnIndex)
  {
    InputData r=requests.get(rowIndex);
    switch(columnIndex)
    {
      case 0:
        return rowIndex;
      case 1:
        return r.getDiffFormatLengthCount();
      case 2:
        return r.getDiffMaterialLengthCount();
      case 3:
        return r.getFormatArea();
      case 4:
        return r.getMaterialArea();

    }
    return "";
  }

  public void clear()
  {
    /*for(ResultsListItem ri:requests)
    {
    if(ri.getResultTabPanel()==null)
    continue;
    JComponent tp=(JTabbedPane)ri.getResultTabPanel().getParent();
    tp.remove(ri.getResultTabPanel());
    }*/
    for(int i=0;i<requests.size();i++)
      removeTest(i);
    requests.clear();
    results.clear();

    fireTableDataChanged();
  }

  /**
   * Добавление нового результата
   * @param r
   */
  public void addResult(ResultsListItem r)
  {
    //resultsList.add(r);
    int d=0;
    for(InputData d1:requests)
    {
      if(compareInputData(d1,r.getInputData()))
        break;
      d++;
    }

    Map<String,ResultsListItem> m;
    if(d==requests.size())
    {
      requests.add(r.getInputData());
      fireTableRowsInserted(requests.size()-1,requests.size()-1);
      m=new HashMap();
      results.add(m);
    }else
    {
      m=results.get(d);
    }
    r=m.put(r.getMethodName(),r);
    selectTest(d);
  }

  /**
   * Удаление отдельного теста
   * @param index номер теста
   * @return
   */
  public void removeTest(int index)
  {
    requests.remove(index);
    Map<String,ResultsListItem> m=results.remove(index);
    for(ResultsListItem res:m.values())
      if(res.getResultTabPanel()!=null)
      {
        JComponent tp=(JTabbedPane)res.getResultTabPanel().getParent();
        tp.remove(res.getResultTabPanel());
      }
    fireTableRowsDeleted(index,index);
    /*
    ResultsListItem res=resultsList.remove(index);
    if(res.getResultTabPanel()!=null)
    {
    JComponent tp=(JTabbedPane)res.getResultTabPanel().getParent();
    tp.remove(res.getResultTabPanel());
    }
    fireTableRowsDeleted(index,index);
    return res;*/
  }

  public int addResult(String testName,Object inputData,Object trimAlgorithm,Object trimResult,long time)
  {
    ResultsListItem ri=new ResultsListItem((TrimResult)trimResult,(Trim)trimAlgorithm,
      (InputData)inputData,time);
    addResult(ri);
    return -1;
  }

  public void clearResults()
  {
    clear();
  }

  public void exportToExcel(String fileName,
    List methods)
    throws FileNotFoundException,IOException
  {
    ExportManager.exportResultListToXLS(new FileOutputStream(fileName),results,methods);
  }

  /**
   * Класс для отображения результатов по конкретному тесту
   */
  public class ResultsTableModel extends AbstractTableModel
  {

    List<ResultsListItem> resultsList=new ArrayList();

    public void setResults(List<ResultsListItem> results)
    {
      this.resultsList=results;
      fireTableDataChanged();
    }

    @Override
    public String getColumnName(int column)
    {

      switch(column)
      {
        case 0:
          return "Method";
        case 1:
          return "MUsed";
        case 2:
          return "Tail";
        case 3:
          return "Patterns";
        case 4:
          return "Efficiency";
        case 5:
          return "Time";
        case 6:
          return "Show";
      }
      return "";
    }

    public int getRowCount()
    {
      return resultsList.size();
    }

    public int getColumnCount()
    {
      return 7;
    }

    public Object getValueAt(int rowIndex,int columnIndex)
    {
      ResultsListItem r=resultsList.get(rowIndex);
      switch(columnIndex)
      {
        case 0:
          return r.getMethodName();
        case 1:
          return r.getUsedMaterialsCount();
        case 2:
          return r.getTail();
        case 3:
          return r.size();
        case 4:
          return r.getEfficiency();
        case 5:
          return r.getTime();
        case 6:
          return r.getResultTabPanel()!=null;
      }
      return "";
    }

    @Override
    public Class<?> getColumnClass(int columnIndex)
    {
      switch(columnIndex)
      {
        case 0:
          return String.class;
        case 1:
          return Integer.class;
        case 2:
          return Integer.class;
        case 3:
          return Integer.class;
        case 4:
          return Double.class;
        case 5:
          return Integer.class;
        case 6:
          return Boolean.class;
      }
      return String.class;
    }

    public ResultsListItem getResult(int i)
    {
      return resultsList.get(i);
    }

    public void hideResult(Component child)
    {
      ResultsListItem ri=null;
      int i=0;
      for(ResultsListItem r:resultsList)
      {
        if(r.getResultTabPanel()==child)
        {
          ri=r;
          break;
        }
        i++;
      }
      if(ri!=null)
      {
        ri.setResultTabPanel(null);
        fireTableRowsUpdated(i,i);
      }
    }

    public void hideResult(int index)
    {
      ResultsListItem ri=resultsList.get(index);
      if(ri.getResultTabPanel()!=null)
      {
        JComponent tp=(JTabbedPane)ri.getResultTabPanel().getParent();
        tp.remove(ri.getResultTabPanel());
        ri.setResultTabPanel(null);
        fireTableRowsUpdated(index,index);
      }
    }
  }
}
